﻿//------------------------------------------------------------------------------
// <copyright company="Tunynet">
//     Copyright (c) Tunynet Inc.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using System.Xml.Linq;
using System.Drawing;
using Tunynet.Imaging;
using Tunynet.Utilities;
using System.IO;
using Tunynet.Settings;

namespace Tunynet.Common
{
    /// <summary>
    /// 租户标识图配置类
    /// </summary>
    [Serializable]
    public class TenantFileSettings
    {        
        private static ConcurrentDictionary<string, TenantFileSettings> registeredTenantAttachmentSettings = new ConcurrentDictionary<string, TenantFileSettings>();

        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="xElement">附件配置节点</param>
        private TenantFileSettings(XElement xElement)
        {
            if (xElement != null)
            {              
                XAttribute att = xElement.Attribute("tenantTypeId");
                if (att != null)
                    _tenantTypeId = att.Value;
                att = xElement.Attribute("storeProviderName");
                if (att != null)
                    _storeProviderName = att.Value;
                att = xElement.Attribute("fileDirectory");
                if (att != null)
                    _fileDirectory = att.Value;
                att = xElement.Attribute("maxFileLength");
                if (att != null)
                    int.TryParse(att.Value, out _maxAttachmentLength);
                att = xElement.Attribute("autoGenerateDirectoryByDate");
                if (att != null)
                    bool.TryParse(att.Value, out _autoGenerateDirectoryByDate);
                att = xElement.Attribute("allowedFileExtensions");
                if (att != null)
                    _allowedFileExtensions = att.Value;
               XElement imageSizeTypeElements = xElement.Elements("imageSettings").FirstOrDefault();
                att = imageSizeTypeElements.Attribute("enableWatermark");
                if (att != null)
                    bool.TryParse(att.Value, out _enableWatermark);
                att = imageSizeTypeElements.Attribute("maxImageHeight");
                if (att != null)
                    int.TryParse(att.Value, out _maxImageHeight);
                att = imageSizeTypeElements.Attribute("maxImageWidth");
                if (att != null)
                    int.TryParse(att.Value, out _maxImageWidth);
                IEnumerable<XElement> thumbnailElements = imageSizeTypeElements.Elements("thumbnail");
                if (thumbnailElements != null && thumbnailElements.Count() > 0)
                {
                    _thumbnailTypes = new ConcurrentDictionary<string, KeyValuePair<Size, ResizeMethod>>();
                    foreach (var thumbnailElement in thumbnailElements)
                    {
                        XAttribute keyAttr = thumbnailElement.Attribute("key");
                        if (keyAttr == null)
                            continue;
                        int width = 0;
                        XAttribute widthAttr = thumbnailElement.Attribute("width");
                        if (widthAttr != null)
                            int.TryParse(widthAttr.Value, out width);
                        int height = 0;
                        XAttribute heightAttr = thumbnailElement.Attribute("height");
                        if (heightAttr != null)
                            int.TryParse(heightAttr.Value, out height);
                        ResizeMethod resizeMethod = ResizeMethod.KeepAspectRatio;
                        XAttribute resizeMethodAttr = thumbnailElement.Attribute("resizeMethod");
                        if (resizeMethodAttr != null)
                            Enum.TryParse<ResizeMethod>(resizeMethodAttr.Value, out resizeMethod);
                        _thumbnailTypes[keyAttr.Value] = new KeyValuePair<Size, ResizeMethod>(new Size(width, height), resizeMethod);
                    }
                }
            }
        }

        /// <summary>
        /// 获取注册的TenantAttachmentSettings
        /// </summary>
        /// <param name="tenantTypeId">租户类型Id</param>
        /// <returns></returns>
        public static TenantFileSettings GetRegisteredSettings(string tenantTypeId)
        {
            TenantFileSettings tenantfilesettings ;
            if (registeredTenantAttachmentSettings.TryGetValue(tenantTypeId, out tenantfilesettings))
                return tenantfilesettings;
            return null;
        }

        /// <summary>
        /// 获取所有注册的TenantAttachmentSettings
        /// </summary>
        /// <returns>TenantAttachmentSettings集合</returns>
        public static IEnumerable<TenantFileSettings> GetAll()
        {
            return registeredTenantAttachmentSettings.Values;
        }

        /// <summary>
        /// 注册TenantAttachmentSettings
        /// </summary>
        /// <remarks>若xElement下有多个add节点，会同时注册多个TenantAttachmentSettings</remarks>
        /// <param name="xElement">附件配置节点，会据此寻找其下所有子节点add</param>
        public static void RegisterSettings(XElement xElement)
        {
            IEnumerable<TenantFileSettings> settings = xElement.Elements("add").Select(n => new TenantFileSettings(n));
            foreach (var setting in settings)
            {
                registeredTenantAttachmentSettings[setting.TenantTypeId] = setting;
            }
        }

        #region 属性
        /// <summary>
        /// 文件目录
        /// </summary>
        private string _fileDirectory = string.Empty;
        public string FileDirectory
        {
            get{ return _fileDirectory;}
            set{_fileDirectory = value;}
        }
        
        private string _storeProviderName = string.Empty;
        /// <summary>
        /// 文件存储功能提供者名称
        /// </summary>
        public string StoreProviderName
        {
            get { return _storeProviderName; }
        }
       
        private string _tenantTypeId = string.Empty;
        /// <summary>
        /// 租户类型Id
        /// </summary>
        public string TenantTypeId
        {
            get { return _tenantTypeId; }

        }

        private bool _enableWatermark = true;
        /// <summary>
        /// 是否允许使用水印
        /// </summary>
        public bool EnableWatermark
        {
            get { return _enableWatermark; }
        }
        private ConcurrentDictionary<string, KeyValuePair<Size, ResizeMethod>> _thumbnailTypes = null;
        /// <summary>
        /// 图片缩略图尺寸类型集合
        /// </summary>
        public ConcurrentDictionary<string, KeyValuePair<Size, ResizeMethod>> ThumbnailTypes
        {
            get { return _thumbnailTypes; }
        }

        private string _tenantImageDirectory = string.Empty;
        /// <summary>
        /// 租户标识图目录
        /// </summary>
        public string TenantImageDirectory
        {
            get { return _tenantImageDirectory; }
        }
        private int _maxImageWidth = 0;
        /// <summary>
        /// 图片最大宽度
        /// </summary>
        public int MaxImageWidth
        {
            get
            {
                if (_maxImageWidth > 0)
                    return _maxImageWidth;

                FileSettings attachmentSettings = DIContainer.Resolve<ISettingsManager<FileSettings>>().Get();
                return attachmentSettings.MaxImageWidth;
            }
        }

        private int _maxImageHeight = 0;
        /// <summary>
        /// 图片最大高度
        /// </summary>
        public int MaxImageHeight
        {
            get
            {
                if (_maxImageHeight > 0)
                    return _maxImageHeight;

                FileSettings attachmentSettings = DIContainer.Resolve<ISettingsManager<FileSettings>>().Get();
                return attachmentSettings.MaxImageHeight;
            }
        }

        private int _maxAttachmentLength = 0;
        /// <summary>
        /// 附件最大长度(单位：K)
        /// </summary>
        public int MaxAttachmentLength
        {
            get
            {
                if (_maxAttachmentLength > 0)
                    return _maxAttachmentLength;

                FileSettings attachmentSettings = DIContainer.Resolve<ISettingsManager<FileSettings>>().Get();
                return attachmentSettings.MaxAttachmentLength;
            }
        }

        private string _allowedFileExtensions = string.Empty;
        /// <summary>
        /// 附件允许的文件扩展名
        /// </summary>
        public string AllowedFileExtensions
        {
            get
            {
                if (!string.IsNullOrEmpty(_allowedFileExtensions))
                    return _allowedFileExtensions;

                FileSettings attachmentSettings = DIContainer.Resolve<ISettingsManager<FileSettings>>().Get();
                return attachmentSettings.AllowedFileExtensions;
            }
        }
        /// <summary>
        /// 是否按yyyy/mm/dd方式自动生成目录
        /// </summary>
        private bool _autoGenerateDirectoryByDate = true;
        public bool AutoGenerateDirectoryByDate
        {
            get
            {
                return _autoGenerateDirectoryByDate;
            }

            set
            {
                _autoGenerateDirectoryByDate = value;
            }
        }

        #endregion

        #region 扩展方法

        /// <summary>
        /// 验证是否支持当前文件扩展名
        /// </summary>
        /// <param name="fileName">文件名（带后缀）</param>
        /// <returns>true-支持,false-不支持</returns>
        public bool ValidateFileExtensions(string fileName)
        {
            string fileExtension = fileName.Substring(fileName.LastIndexOf(".") + 1);
            string[] extensions = AllowedFileExtensions.Split(',');

            return extensions.Where(n => n.Equals(fileExtension, StringComparison.InvariantCultureIgnoreCase)).Count() > 0;
        }

        /// <summary>
        /// 验证文件大小是否超出限制
        /// </summary>
        /// <param name="contentLength">需要验证的文件大小</param>
        /// <returns>true-未超出限制,false-超出限制</returns>
        public bool ValidateFileLength(int contentLength)
        {
            return contentLength < (long)MaxAttachmentLength * 1024;
        }

        #endregion        
        
    }
}
